import type {
  ElementStyleConfig,
  PlatformStyleConfig,
  StatePrefixMap,
  StyleConfig,
} from '../../../../lib/abstract'
import type {
  ComponentStyleIdType,
  PlatformTypeValue,
} from '../../../../types/interfaces'
import { BaseModule } from '../../../../lib/abstract'
import { createStandardStyleTag } from '../../../../lib/style_injector'
import { ToolKit } from '../../../../lib/utils/toolkit'
import { ComponentStyleId, HOSTNAME, logger } from '../../../../types/constants'
import {
  StyleInjectPosition,
  SYMBOLS,
} from '../../../../types/interfaces'
import { ConfigManager } from '../../../config_manager'

interface Config {
  enabled?: boolean
}

/**
 * 样式增强模块（单例模式）
 */
export class StyleEnhancement extends BaseModule {
  readonly id: string = 'style_enhancement'
  readonly styleId: string = ComponentStyleId[this.name]
  readonly isInitialized: boolean = false
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  private static instance: StyleEnhancement
  private styleElement: HTMLStyleElement | null = null
  private platformStyles: PlatformStyleConfig = {}

  private readonly statePrefixMap: StatePrefixMap = {
    hover: ':hover',
    active: ':active',
    focus: ':focus',
    disabled: ':disabled',
  }

  config: Config = {
    enabled: true,
  }

  get name(): ComponentStyleIdType {
    return 'StyleEnhancement'
  }

  constructor() {
    super()
    this.initStyleElement()
  }

  public static getInstance(): StyleEnhancement {
    if (!StyleEnhancement.instance) {
      StyleEnhancement.instance = new StyleEnhancement()
    }
    return StyleEnhancement.instance
  }

  handleCleanupReferences(): void {
    // 1. 检查并记录初始状态
    const elementExists = !!this.styleElement
    const wasInDOM = elementExists && document.contains(this.styleElement)

    try {
      // 2. 安全移除
      if (elementExists) {
        if (wasInDOM) {
          this.styleElement!.remove()
          logger.important(`[${this.name}] Removed style element from DOM`)
        }
        else {
          logger.warn(`[${this.name}] Style element was not in DOM`)
        }

        // 3. 清理引用
        this.styleElement = null

        // 4. 验证移除结果
        if (wasInDOM && document.contains(this.styleElement)) {
          throw new Error('Style element still exists in DOM after removal')
        }
      }
    }
    catch (error: any) {
      logger.error(`[${this.name}] Destruction failed`, error, {
        elementExists,
        wasInDOM,
      })
      this.styleElement = null // 确保无论如何都清理引用
    }
    finally {
      // 5. 辅助 GC
      if (this.styleElement) {
        this.styleElement.textContent = ''
      }
    }
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.applyPlatformStyles()
    logger.important(`[MBF] ${SYMBOLS.OTHERS.PALETTE} 页面样式已美化`)
  }

  onToggleCallback(_id: string, checked: boolean): void {
    if (checked) {
      this.initStyleElement()
      this.core()
    }
    else {
      this.destroy()
    }
  }

  /**
   * 初始化样式标签
   */
  private initStyleElement(force: boolean = false): void {
    if (this.styleElement && !force)
      return

    this.styleElement = createStandardStyleTag(this.styleId, '', { allowEmpty: true, position: StyleInjectPosition.First })
  }

  /**
   * 注册平台样式
   * @param platform 平台名称
   * @param configs 样式配置数组
   */
  registerPlatform(platform: PlatformTypeValue, configs: StyleConfig): void {
    this.platformStyles[platform] = {
      config: configs.config,
      styles: configs.styles,
    }
  }

  /**
   * 检查元素配置是否应应用
   * @param config 元素配置
   */
  private shouldApplyConfig(config: ElementStyleConfig): boolean {
    if (config.enabled === false)
      return false
    if (typeof config.condition === 'function')
      return config.condition()
    if (typeof config.condition === 'boolean')
      return config.condition
    return true
  }

  /**
   * 使用 !important 应用样式
   * @param $elements jQuery 元素集合
   * @param styles 样式对象
   */
  private applyStylesWithImportant(
    $elements: JQuery<HTMLElement>,
    styles: Record<string, string>,
  ) {
    $elements.each((_, element) => {
      const el = element as HTMLElement
      Object.entries(ToolKit.ui.style.normalizeStyles(styles)).forEach(([prop, value]) => {
        // 确保值包含 !important
        const notImportantValue = value.includes('!important')
          ? value.replace('!important', '').trim()
          : value
        el.style.setProperty(prop, notImportantValue, 'important')
      })
    })
  }

  /**
   * 应用内联样式
   * @param configs 样式配置数组
   */
  private applyInlineStyles(configs: ElementStyleConfig[]) {
    configs.forEach((config) => {
      if (!this.shouldApplyConfig(config) || config.inline !== true)
        return

      const elements = $(config.selector)
      if (elements.length === 0)
        return

      const styles = config.styles || {}

      // 应用基础样式
      if (styles.normal) {
        this.applyStylesWithImportant(elements, styles.normal)
      }
    })
  }

  /**
   * 生成 CSS 规则字符串
   */
  private generateStyleRules(styles: Record<string, string>): string {
    return Object.entries(styles)
      .filter(([prop, _]) => !prop.startsWith('_'))
      .map(([prop, value]) => {
        const cssProp = prop.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`)
        return `\t${cssProp}: ${value} !important;`
      })
      .join('\n')
  }

  /**
   * 生成容器 CSS 规则
   * @param config 元素配置
   */
  private generateContainerStyleRules(config: ElementStyleConfig): string {
    if (!this.shouldApplyConfig(config))
      return ''

    let rules = '\n'

    const styles = config.styles || {}

    // 处理基础样式
    if (styles.normal) {
      rules += `${config.selector} {\n${this.generateStyleRules(styles.normal)}  \n}\n`
    }

    // 处理交互状态样式
    const interactiveStates: (keyof StatePrefixMap)[] = ['hover', 'active', 'focus', 'disabled']

    interactiveStates.forEach((state) => {
      const stateStyles = styles[state]
      if (stateStyles) {
        rules += `${config.selector}${this.statePrefixMap[state]} {\n${this.generateStyleRules(stateStyles)} \n}\n`
      }
    })
    return rules
  }

  /**
   * 生成深色模式 CSS 规则
   * @param config 元素配置
   */
  private generateDarkModeStyleRules(config: ElementStyleConfig): string {
    if (!config.darkStyles)
      return ''

    let darkStyles = ''
    const styles = config.darkStyles

    // 深色模式基础样式
    if (styles && styles.normal) {
      darkStyles += `
        ${config.selector} {
          ${this.generateStyleRules(styles.normal)}
        }\n
      `
    }

    const interactiveStates: (keyof StatePrefixMap)[] = ['hover', 'active', 'focus', 'disabled']
    interactiveStates.forEach((state) => {
      if (!styles)
        return
      const stateStyles = styles[state]
      if (stateStyles) {
        darkStyles += `
          ${config.selector}:${state} {
            ${this.generateStyleRules(stateStyles)}
          }\n
        `
      }
    })

    return darkStyles
      ? `\n@media (prefers-color-scheme: dark) {\n${darkStyles}\n}`
      : ''
  }

  /**
   * 生成指定平台样式
   * @param platform 平台名称
   */
  private generatePlatformStyles(platform: PlatformTypeValue): string {
    const configs = this.platformStyles[platform].config
    if (!configs || !this.styleElement)
      return ''

    let cssText = ''

    configs.forEach((config) => {
      if (!this.shouldApplyConfig(config))
        return

      // 生成基础样式
      cssText += this.generateContainerStyleRules(config)
      // 生成深色模式样式
      cssText += this.generateDarkModeStyleRules(config)
    })

    // 应用内联样式
    this.applyInlineStyles(configs)

    return cssText
  }

  /**
   * 应用平台样式
   */
  private applyPlatformStyles(): void {
    if (!this.styleElement) {
      logger.warn(`[${this.name}] ⚠️ 样式元素未初始化，跳过应用样式`)
      return
    }

    let cssText = ''
    // 应用平台样式
    Object.keys(this.platformStyles).filter(platform => platform === HOSTNAME).forEach((platform) => {
      cssText += this.generatePlatformStyles(platform)
      cssText += this.platformStyles[platform].styles
    })

    this.styleElement.textContent = cssText
  }

  /**
   * 刷新平台样式
   * @param configs 样式配置数组
   * @param force 是否强制刷新
   */
  refreshPlatformStyles(configs: StyleConfig, force: boolean = false): void {
    this.initStyleElement(force)
    this.registerPlatform(HOSTNAME, configs)
    this.applyPlatformStyles()
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }
}
